package com.sprouting.ops.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sprouting.ops.annotations.invoke.IdempotentSingle;
import com.sprouting.ops.enums.CloudTypeEnum;
import com.sprouting.ops.enums.ComputerSpecialEnum;
import com.sprouting.ops.interfaces.AddGroup;
import com.sprouting.ops.interfaces.ConstantBase;
import com.sprouting.ops.interfaces.UpdGroup;
import com.sprouting.ops.model.DromaraFileStorage;
import com.sprouting.ops.model.OpsComputerServer;
import com.sprouting.ops.model.ResultJson;
import com.sprouting.ops.model.qo.ComputerServerAllQo;
import com.sprouting.ops.model.qo.OpsComputerServerQo;
import com.sprouting.ops.model.vo.DeployPortVo;
import com.sprouting.ops.model.vo.OpsComputerServerVo;
import com.sprouting.ops.service.DromaraFileStorageService;
import com.sprouting.ops.service.OpsComputerServerService;
import com.sprouting.ops.service.OpsDeployService;
import com.sprouting.ops.service.OpsDeployToolService;
import com.sprouting.ops.utils.CheckTool;
import com.sprouting.ops.utils.EntityTool;
import com.sprouting.ops.utils.IdTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务器与计算机信息表
 *
 * @author ：LX（长沙麓谷）
 * @date 创建时间： 2023/11/8 16:35
 */
@Slf4j
@RestController
@RequestMapping("computer")
public class OpsComputerServerController {

    @Resource
    private OpsComputerServerService opsComputerServerService;
    @Resource
    private DromaraFileStorageService dromaraFileStorageService;
    @Resource
    private OpsDeployToolService opsDeployToolService;
    @Resource
    private OpsDeployService opsDeployService;


    /**
     * 获取可迁移的目标计算机
     * @param computerServerId 当前计算机
     * @return
     */
    @PostMapping("getTransfer")
    public ResultJson getTransfer(String computerServerId){
        if (CheckTool.checkNull(computerServerId)){
            return ResultJson.errorCheck();
        }
        OpsComputerServer server = opsComputerServerService.getById(computerServerId);
        if (server == null){
            return ResultJson.success();
        }

        // 排除自身、子级、自己的当前父级（应该也可以用的）
        // List<OpsComputerServerVo> list;
        // if (ConstantBase.DefaultValue.STRING.equals(server.getParentId())){
        //     // 顶级节点
        //     list = opsComputerServerService.getTransfer(computerServerId, null);
        // } else {
        //     list = opsComputerServerService.getTransfer(computerServerId, server.getParentId());
        // }

        List<OpsComputerServerVo> list = opsComputerServerService.getBySiteId(server.getSiteId());
        if (CollUtil.isEmpty(list)){
            return ResultJson.success();
        }

        // 补充数据
        buildData(list);

        // 排列成树
        List<OpsComputerServerVo> rootTree = buildTree(list);

        // 裁切掉树
        delThisNode(rootTree, server);
        if (CollUtil.isEmpty(rootTree)){
            return ResultJson.success();
        }

        // 遍历出剩下的数据
        List<OpsComputerServerVo> countList = new ArrayList<>();
        getTransferUser(countList, rootTree);

        if (!ConstantBase.DefaultValue.STRING.equals(server.getParentId())){
            // 父级不是最顶级的，则加上根可以迁移
            OpsComputerServerVo vo = new OpsComputerServerVo();
            vo.setId(ConstantBase.DefaultValue.STRING);
            vo.setName("根节点");
            countList.add(vo);
        }

        return ResultJson.success(countList);
    }


    /**
     * 迁移数据用户到另外一个计算机下面
     * @param computerServerId 要迁移数据的ID
     * @param targetId 迁移的目标
     * @return
     */
    @PostMapping("migrate")
    public ResultJson migrate(String computerServerId, String targetId){
        // 应该校验下相关数据，比如目标是否回环，是否本系统的数据，但这里暂不考虑这种情况
        if (CheckTool.checkNull(computerServerId, targetId)){
            return ResultJson.errorCheck();
        }

        OpsComputerServer server = opsComputerServerService.getById(computerServerId);
        if (server == null){
            return ResultJson.success();
        }
        // 校验目标节点是否存在（如果不是根节点）
        OpsComputerServer targetServer = null;
        if (!ConstantBase.DefaultValue.STRING.equals(targetId)) {
            targetServer = opsComputerServerService.getById(targetId);
            if (targetServer == null) {
                return ResultJson.error("目标节点不存在");
            }
        }
        // 防止迁移到自身
        if (computerServerId.equals(targetId)) {
            return ResultJson.error("不能迁移到自身");
        }

        List<OpsComputerServerVo> sonNodeList = opsComputerServerService.getSonByParentId(computerServerId);

        // 对于所有的子级之前用的就是这个父级ids
        String oldParentIds = server.getParentIds();
        if (StrUtil.isEmpty(oldParentIds)){
            // 那之前应该就是根节点下面的
            oldParentIds = server.getId();
        } else {
            oldParentIds = server.getParentId() + "," + server.getId();
        }

        if (ConstantBase.DefaultValue.STRING.equals(targetId)){
            // 迁移到了根节点下面
            server.setParentId(targetId);
            server.setParentIds("");

        } else {
            // 普通节点
            server.setParentId(targetId);
            if (StrUtil.isEmpty(targetServer.getParentIds())){
                // 上级如果是根节点下面的第一个节点，父级id是没有东西的
                server.setParentIds(targetServer.getId());
            } else {
                server.setParentIds(targetServer.getParentIds() + "," + targetId);
            }
        }

        if (CollUtil.isNotEmpty(sonNodeList)){
            for (OpsComputerServerVo opsComputerServerVo : sonNodeList) {
                String parentIds = opsComputerServerVo.getParentIds();
                String replace = parentIds.replace(oldParentIds, server.getParentIds() + "," + server.getId());
                opsComputerServerVo.setParentIds(replace);
            }
        }

        opsComputerServerService.migrate(sonNodeList, server);
        return ResultJson.success();
    }

    /**
     * 管理员- 查询全部的计算机
     * @param query 查询参数
     * @return
     */
    @PostMapping("getAllComputerServerPageList")
    public ResultJson getAllComputerServerPageList(ComputerServerAllQo query){
        if (query == null){
            query = new ComputerServerAllQo();
        }
        Page<OpsComputerServerVo> pageList = opsComputerServerService.getAllComputerServerPageList(query.getPage(), query);
        List<OpsComputerServerVo> records = pageList.getRecords();
        if (CollUtil.isEmpty(records)){
            return ResultJson.success(pageList);
        }

        buildData(records);

        return ResultJson.success(pageList);
    }

    /**
     * 找到占用的端口（不分页）
     * @param computerServerId 服务器id
     * @return
     */
    @PostMapping("getPort")
    public ResultJson getPort(String computerServerId){
        if (CheckTool.checkNull(computerServerId)){
            return ResultJson.errorCheck();
        }

        // 找到工具
        List<DeployPortVo> deployToolPortList = opsDeployToolService.getByComputerServerId(computerServerId);
        // 找到组件
        List<DeployPortVo> componentPortList = opsDeployService.getComponentByComputerServerId(computerServerId);
        // 找到应用
        List<DeployPortVo> appPortList = opsDeployService.getAppByComputerServerId(computerServerId);

        List<DeployPortVo> finalList = new ArrayList<>();
        if (CollUtil.isNotEmpty(deployToolPortList)){
            for (DeployPortVo deployPortVo : deployToolPortList) {
                String[] split = deployPortVo.getPorts().split(",");
                for (String port : split) {
                    DeployPortVo bo = BeanUtil.copyProperties(deployPortVo, DeployPortVo.class);
                    bo.setPorts(port);
                    bo.setTypeName("工具");
                    finalList.add(bo);
                }
            }
        }
        if (CollUtil.isNotEmpty(componentPortList)){
            for (DeployPortVo deployPortVo : componentPortList) {
                String[] split = deployPortVo.getPorts().split(",");
                for (String port : split) {
                    DeployPortVo bo = BeanUtil.copyProperties(deployPortVo, DeployPortVo.class);
                    bo.setPorts(port);
                    bo.setTypeName("组件");
                    finalList.add(bo);
                }
            }
        }
        if (CollUtil.isNotEmpty(appPortList)){
            for (DeployPortVo deployPortVo : appPortList) {
                String[] split = deployPortVo.getPorts().split(",");
                for (String port : split) {
                    DeployPortVo bo = BeanUtil.copyProperties(deployPortVo, DeployPortVo.class);
                    bo.setPorts(port);
                    bo.setTypeName("应用");
                    finalList.add(bo);
                }
            }
        }

        return ResultJson.success(finalList);
    }


    /**
     * 找到下级
     * @param id 上级节点
     * @return
     */
    @PostMapping("getSonNode")
    public ResultJson getSonNode(String id){
        if (CheckTool.checkNull(id)){
            return ResultJson.errorCheck();
        }
        List<OpsComputerServerVo> sonNodeList = opsComputerServerService.getSonNode(id);
        buildData(sonNodeList);
        return ResultJson.success(sonNodeList);
    }

    /**
     * 查询现场计算机树
     * @param query 查询参数
     * @return
     */
    @PostMapping("getComputerServerTree")
    public ResultJson getComputerServerTree(@Validated OpsComputerServerQo query){
        List<OpsComputerServerVo> list = opsComputerServerService.getBySiteId(query.getSiteId());
        if (CollUtil.isEmpty(list)){
            return ResultJson.success();
        }

        // 补充数据
        buildData(list);

        // 排列成树
        List<OpsComputerServerVo> rootTree = buildTree(list);

        // todo 过滤

        return ResultJson.success(rootTree);
    }

    /**
     * 计算机详情
     * @param computerServerId 计算机id
     * @return
     */
    @PostMapping("getComputerServerDetails")
    public ResultJson getComputerServerDetails(String computerServerId){
        if (CheckTool.checkNull(computerServerId)){
            return ResultJson.errorCheck();
        }

        OpsComputerServer server = opsComputerServerService.getById(computerServerId);
        if (server == null){
            return ResultJson.errorCheck();
        }

        OpsComputerServerVo vo = BeanUtil.copyProperties(server, OpsComputerServerVo.class);
        if (!ConstantBase.DefaultValue.STRING.equals(vo.getParentId())){
            OpsComputerServer parent = opsComputerServerService.getById(vo.getParentId());
            vo.setParentName(parent.getName());
        }
        // 补充数据
        buildData(ListUtil.of(vo));

        return ResultJson.success(vo);
    }

    /**
     * 分页查询 服务器与计算机信息
     * @param query 查询参数
     * @return
     */
    @PostMapping("getComputerServerPageList")
    public ResultJson getComputerServerPageList(@Validated OpsComputerServerQo query){
        Page page = query.getPage();
        Page<OpsComputerServerVo> computerServerPageList = opsComputerServerService.getComputerServerPageList(page, query);
        if (CollUtil.isEmpty(computerServerPageList.getRecords())){
            return ResultJson.success(computerServerPageList);
        }

        buildData(computerServerPageList.getRecords());

        return ResultJson.success(computerServerPageList);
    }

    /**
     * 获取云主机类型
     * @return
     */
    @RequestMapping("getCloudType")
    public ResultJson getCloudType(){
        List<Map<String, Object>> list = new ArrayList<>();
        for (CloudTypeEnum data : CloudTypeEnum.values()) {
            Map<String, Object> map = new HashMap<>();
            map.put("code", data.getCode());
            map.put("name", data.getName());
            list.add(map);
        }
        return ResultJson.success(list);
    }

    /**
     * 获取特殊机器类型
     * @return
     */
    @RequestMapping("getComputerSpecial")
    public ResultJson getComputerSpecial(){
        List<Map<String, Object>> list = new ArrayList<>();
        for (ComputerSpecialEnum data : ComputerSpecialEnum.values()) {
            Map<String, Object> map = new HashMap<>();
            map.put("code", data.getCode());
            map.put("name", data.getName());
            list.add(map);
        }
        return ResultJson.success(list);
    }

    /**
     * 保存一个服务器或计算机
     * @param opsComputerServer 服务器或计算机
     * @return
     */
    @IdempotentSingle
    @PostMapping("saveComputerServer")
    public ResultJson saveComputerServer(@Validated(AddGroup.class) OpsComputerServer opsComputerServer){
        String msg = checkComputerServer(opsComputerServer);
        if (msg != null){
            return ResultJson.error(msg);
        }

        if (ConstantBase.DefaultValue.STRING.equals(opsComputerServer.getParentId())){
            // 顶级节点
            opsComputerServer.setParentIds(null);
        } else {
            // 隶属某个节点下的
            OpsComputerServer parent = opsComputerServerService.getById(opsComputerServer.getParentId());
            if (CheckTool.checkNull(parent.getParentIds())){
                // 上级节点是顶级节点，没有上级，直接填上级即可
                opsComputerServer.setParentIds(parent.getId());
            } else {
                opsComputerServer.setParentIds(parent.getParentIds() + "," + parent.getId());
            }
        }

        opsComputerServer.setId(IdTool.getId());
        EntityTool.saveBase(opsComputerServer);

        // 提取Markdown的数据
        List<DromaraFileStorage> dromaraFileStorageList = dromaraFileStorageService.getMarkdownImagesUrlToFileStorage(opsComputerServer.getAccess1(), opsComputerServer.getId(), ConstantBase.FileSourceType.ACCESS);
        opsComputerServerService.saveComputerServer(opsComputerServer, dromaraFileStorageList);
        return ResultJson.success(opsComputerServer);
    }

    /**
     * 更新一个服务器或计算机
     * @param opsComputerServer 服务器或计算机
     * @return
     */
    @IdempotentSingle
    @PostMapping("updComputerServer")
    public ResultJson updComputerServer(@Validated(UpdGroup.class) OpsComputerServer opsComputerServer){
        String msg = checkComputerServer(opsComputerServer);
        if (msg != null){
            return ResultJson.error(msg);
        }

        // 不允许修改上级
        opsComputerServer.setParentIds(null);
        opsComputerServer.setParentId(null);

        EntityTool.updBase(opsComputerServer);
        // 修改的时候也要提取，然后转换为生产的数据，这里要注意的是，修改的时候，不考虑去删除旧的数据的问题，到时候删除的时候，直接使用objId统一处理即可，因为这个数据量还是比较小的，没必要找的旧的去删，新的去加，搞麻烦了
        List<DromaraFileStorage> dromaraFileStorageList = dromaraFileStorageService.getMarkdownImagesUrlToFileStorage(opsComputerServer.getAccess1(), opsComputerServer.getId(), ConstantBase.FileSourceType.ACCESS);
        opsComputerServerService.updComputerServer(opsComputerServer, dromaraFileStorageList);
        return ResultJson.success(opsComputerServer);
    }

    /**
     * 删除一个 服务器或计算机
     * @param computerServerId 服务器或计算机id
     * @return
     */
    @IdempotentSingle
    @PostMapping("delComputerServer")
    public ResultJson delComputerServer(String computerServerId){
        if (CheckTool.checkNull(computerServerId)){
            return ResultJson.errorCheck();
        }

        OpsComputerServer computerServer = opsComputerServerService.getById(computerServerId);
        if (computerServer == null){
            return ResultJson.success();
        }
        List<OpsComputerServerVo> sonList = opsComputerServerService.getSonByParentId(computerServer.getId());
        if (CollUtil.isNotEmpty(sonList)){
            return ResultJson.error("存在下级节点，请先删除下级节点才能删除当前计算机");
        }

        List<DromaraFileStorage> accessList = dromaraFileStorageService.getByBindId(computerServerId);

        // List<String> urlList = dromaraFileStorageService.getMarkdownImagesUrl(computerServer.getAccess1());
        opsComputerServerService.delComputerServer(computerServer, accessList);
        return ResultJson.success();
    }

    /**
     * 构建生成树
     * @param treeList 所有文件
     * @return 生成的树
     */
    private List<OpsComputerServerVo> buildTree(List<OpsComputerServerVo> treeList){
        if (CollUtil.isEmpty(treeList)){
            return null;
        }
        // 获取到根节点
        List<OpsComputerServerVo> rootList = treeList.stream().filter(i -> ConstantBase.DefaultValue.STRING.equals(i.getParentId())).sorted(Comparator.comparing(OpsComputerServerVo::getCreateTime)).collect(Collectors.toList());
        if (CollUtil.isEmpty(rootList)){
            log.error("[权限] 当前权限树异常，未查询到当前系统顶级节点!用户ID->{}", StpUtil.getLoginId());
            return null;
        }

        for (OpsComputerServerVo tree : rootList){
            getChild(tree, treeList);
        }

        return rootList;
    }

    /**
     * 获取文件子节点
     * @param tree 当前文件
     * @param treeList 全部文件
     */
    private void getChild(OpsComputerServerVo tree, List<OpsComputerServerVo> treeList){
        List<OpsComputerServerVo> childList = treeList.stream().filter(obj -> tree.getId().equals(obj.getParentId())).sorted(Comparator.comparing(OpsComputerServerVo::getCreateTime)).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(childList)){
            tree.setChildren(childList);

            for (OpsComputerServerVo siteFile : childList){
                siteFile.setParentName(tree.getName());
                getChild(siteFile, treeList);
            }
        }
    }

    /**
     * 检查 和 补充默认数据
     * @param opsComputerServer 服务器或计算机
     * @return 非null则有异常
     */
    private String checkComputerServer(OpsComputerServer opsComputerServer){
        if (!CheckTool.checkNull(opsComputerServer.getIps())){
            String ips = opsComputerServer.getIps()
                    // 中文逗号转英文
                    .replaceAll("，", ",")
                    // 去除空格
                    .replaceAll("\\s+", "")
                    // 合并多个连续逗号
                    .replaceAll(",+", ",");
            // 去除首尾逗号，然后在结尾添加一个逗号用于精确匹配
            // 检查最后是否有一个逗号，没有就要处理添加一个。否则会出现192.168.1.1 和 192.168.1.11 都查询出的情况
            ips = StrUtil.trim(ips, ',');

            if (StrUtil.isNotEmpty(ips)){
                String[] split = ips.split(",");
                for (String ip : split) {
                    // 判断IP是否已经注册
                    if (CheckTool.checkNull(ip)){
                        continue;
                    }
                    if (Validator.isIpv4(ip) || Validator.isIpv6(ip)){

                    } else {
                        return String.format("IP地址：[%s]无效", ip);
                    }
                    OpsComputerServer dbIp = opsComputerServerService.getBySiteAndIpFilterId(opsComputerServer.getId(), opsComputerServer.getSiteId(), ip + ",");
                    if (dbIp != null){
                        return String.format("IP地址已存在主机：%s 。主机名： %s", dbIp.getName(), dbIp.getHostName());
                    }
                }
            }
        }
        if (ConstantBase.DefaultValue.STRING.equals(opsComputerServer.getParentId())){
            // 父级
        } else {
            // 非根节点
            OpsComputerServer parent = opsComputerServerService.getById(opsComputerServer.getParentId());
            if (parent == null){
                return "无效的上级计算机";
            }

            // 与当前数据同级的
            List<OpsComputerServerVo> sameList = opsComputerServerService.getSonByParentId(parent.getId());

            if (parent.getCore() != null && opsComputerServer.getCore() != null){
                // 已使用的份额
                int coreSum = 0;
                if (CollUtil.isNotEmpty(sameList)){
                    // 核心数
                    coreSum = sameList.stream().mapToInt(obj -> Objects.isNull(obj.getCore()) ? 0 : obj.getCore()).sum();
                }
                if (parent.getCore() < coreSum + opsComputerServer.getCore()){
                    return String.format("所有CPU核心数超过父级最大数量，最大只能选择 [%s] 核", parent.getCore() - coreSum);
                }
            }

            if (parent.getMemory() != null && opsComputerServer.getMemory() != null){
                double memorySum = 0;
                if (CollUtil.isNotEmpty(sameList)){
                    // 内存数
                    memorySum = sameList.stream().mapToDouble(obj -> Objects.isNull(obj.getMemory()) ? 0 : obj.getMemory()).sum();
                }
                if (parent.getMemory() < memorySum + opsComputerServer.getMemory()){
                    return String.format("所有内存超过父级最大数量，最大只能选择 [%s] 内存", parent.getMemory() - memorySum);
                }
            }

            if (parent.getAccessNetworkSizeUp() != null && opsComputerServer.getAccessNetworkSizeUp() != null){
                double accessNetworkSizeUpSum = 0;
                if (CollUtil.isNotEmpty(sameList)){
                    // 上行
                    accessNetworkSizeUpSum = sameList.stream().mapToDouble(obj -> Objects.isNull(obj.getAccessNetworkSizeUp()) ? 0 : obj.getAccessNetworkSizeUp()).sum();
                }
                if (parent.getAccessNetworkSizeUp() < accessNetworkSizeUpSum + opsComputerServer.getAccessNetworkSizeUp()){
                    return String.format("所有上行超过父级最大数量，最大只能选择 [%s] M", parent.getAccessNetworkSizeUp() - accessNetworkSizeUpSum);
                }
            }

            if (parent.getAccessNetworkSizeDown() != null && opsComputerServer.getAccessNetworkSizeDown() != null){
                double accessNetworkSizeDownSum = 0;
                if (CollUtil.isNotEmpty(sameList)){
                    // 下行
                    accessNetworkSizeDownSum = sameList.stream().mapToDouble(obj -> Objects.isNull(obj.getAccessNetworkSizeDown()) ? 0 : obj.getAccessNetworkSizeDown()).sum();
                }
                if (parent.getAccessNetworkSizeDown() < accessNetworkSizeDownSum + opsComputerServer.getAccessNetworkSizeDown()){
                    return String.format("所有下行超过父级最大数量，最大只能选择 [%s] M", parent.getAccessNetworkSizeDown() - accessNetworkSizeDownSum);
                }
            }
        }

        /// --- 补充数据

        if (opsComputerServer.getCloudType() != null){
            // 是云主机则必然是虚拟机
            opsComputerServer.setVm(ConstantBase.YesOrNo.YES);
        }
        if (opsComputerServer.getSpecial() == null){
            opsComputerServer.setSpecial(ComputerSpecialEnum.ORDINARY.getCode());
        }
        if (opsComputerServer.getUseStatus() == null){
            opsComputerServer.setUseStatus(ConstantBase.Use.USE);
        }
        if (opsComputerServer.getLinchpin() == null){
            opsComputerServer.setLinchpin(ConstantBase.YesOrNo.YES);
        }

        return null;
    }

    /**
     * 拼接必要的参数
     * @param opsComputerServerVoList 要补充的对象
     */
    private void buildData(List<OpsComputerServerVo> opsComputerServerVoList){
        for (OpsComputerServerVo computerServer : opsComputerServerVoList) {
            computerServer.setRandomId(IdTool.getId());
            // 特殊机器
            if (computerServer.getSpecial() != null){
                ComputerSpecialEnum specialEnum = ComputerSpecialEnum.getByCode(computerServer.getSpecial());
                if (specialEnum != null){
                    computerServer.setSpecialName(specialEnum.getName());
                }
            }

            // 云主机类型
            if (computerServer.getCloudType() != null){
                CloudTypeEnum cloudTypeEnum = CloudTypeEnum.getByCode(computerServer.getCloudType());
                if (cloudTypeEnum != null){
                    computerServer.setCloudTypeName(cloudTypeEnum.getName());
                }
            }

            if (computerServer.getOs() != null){
                computerServer.setOsTypeName(ConstantBase.OsType.MAP.get(computerServer.getOs()));
            }

            if (computerServer.getSonNum() == null || computerServer.getSonNum() == 0){
                computerServer.setHasChildren(false);
            } else {
                computerServer.setHasChildren(true);
            }
        }
    }

    /**
     * 删除自身的数据
     * @param rootTree 全部树
     * @param server 当前计算机
     */
    private void delThisNode(List<OpsComputerServerVo> rootTree, OpsComputerServer server) {
        if (CollUtil.isEmpty(rootTree)){
            return;
        }
        Iterator<OpsComputerServerVo> iterator = rootTree.iterator();
        while (iterator.hasNext()) {
            OpsComputerServerVo child = iterator.next();
            if (child.getId().equals(server.getId())) {
                // 如果找到了目标节点，直接删除该节点
                iterator.remove();
                return;
            } else {
                // 否则递归删除子树中的目标节点
                delThisNode(child.getChildren(), server);
            }
        }
    }

    /**
     * 遍历可迁移的用户
     * @param countList 存储最终迁移的
     * @param tree 要遍历的树
     */
    private void getTransferUser(List<OpsComputerServerVo> countList, List<OpsComputerServerVo> tree){
        for (OpsComputerServerVo familyTree : tree) {
            countList.add(familyTree);
            if (CollUtil.isNotEmpty(familyTree.getChildren())){
                getTransferUser(countList, familyTree.getChildren());
            }
        }
    }
}
